﻿/// <reference path="jquery-1.11.3.js" />
/// <reference path="jquery.cookie.js" />
/// <reference path="jquery-ui-1.11.4.js" />
/// <reference path="bootstrap.js" />
/// <reference path="odatajs-4.0.0.js" />

/* global odatajs */

// *** home ***

var $home = {
};

// *** observer design pattern ***

$home.observable = function () {
    this.handlers = [];
};

$home.observable.prototype.subscribe = function (fn) {
    this.handlers.push(fn);
};

$home.observable.prototype.unsubscribe = function (fn) {
    this.handlers = this.handlers.filter(function (handler) {
        if (handler !== fn) {
            return handler;
        }
    });
};

$home.observable.prototype.fire = function (argument, owner) {
    var scope = owner || window;
    this.handlers.forEach(function (handler) {
        handler.call(scope, argument);
    });
};

// *** UI ***

$home.ui = (function () {
    return {
    };
})();

// *** utility ***

$home.utility = (function () {
    return {
        queryString: {
            getParameterByName: function (name) {
                name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
                var regex = new RegExp("[\\?&]" + name + "=([^&#]*)");
                var results = regex.exec(location.search);
                return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
            }
        },

        date: {
            getDateFormat: function () {
                return "yyyy-M-d";
            },

            getDateTimeFormat: function () {
                return $home.utility.date.getDateFormat() + " h:m:s";
            },

            toLocalDateString: function (date) {
                var format = $home.utility.date.getDateFormat();
                return format.replace("yyyy", date.getFullYear().toString())
                    .replace("M", (date.getMonth() + 1).toString())
                    .replace("d", date.getDate().toString());
            },

            toLocalDateTimeString: function (date) {
                var format = $home.utility.date.getDateTimeFormat();
                return format.replace("yyyy", date.getFullYear().toString())
                    .replace("M", (date.getMonth() + 1).toString())
                    .replace("d", date.getDate().toString())
                    .replace("h", date.getHours().toString())
                    .replace("m", date.getMinutes().toString())
                    .replace("s", date.getSeconds().toString());
            },

            toServerDateString: function (date) {
                return "yyyy-M-d".replace("yyyy", date.getFullYear().toString())
                    .replace("M", (date.getMonth() + 1).toString())
                    .replace("d", date.getDate().toString());
            }
        },

        odata: {
            toODataDateTimeOffset: function (value) {
                if (value) {
                    value.__edmType = "Edm.DateTimeOffset";
                    value.__offset = "Z";
                }
                return value;
            },

            removeMetadataProperties: function (entity) {
                if (entity && $.isPlainObject(entity)) {
                    for (var property in entity) {
                        if (property.indexOf("@") >= 0) {
                            entity[property] = undefined;
                        }
                    }
                }
            }
        },

        guid: {
            generate: function () {
                // see http://guid.us/GUID/JavaScript
                // This code just random GUIDs they are not claimed to be unique. Don't use these if its very important.

                function S4() {
                    return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
                }

                // then to call it, plus stitch in '4' in the third group
                return (S4() + S4() + "-" + S4() + "-4" + S4().substr(0, 3) + "-" + S4() + "-" + S4() + S4() + S4()).toLowerCase();
            }
        }
    };
})();

// *** optimization ***

$home.optimization = (function () {
    return {
        comment: function (entity) {
            entity.VisitorId = $.cookie("home_visitor_id");
            odatajs.oData.request({
                requestUri: "/services/optimizationservice/Comments",
                method: "POST",
                data: entity
            }, $.noop, $.noop);
        },

        visit: function (entity) {
            var param = $home.optimization.internal.createVisitEntity();
            entity = $.extend(param, entity);
            odatajs.oData.request({
                requestUri: "/services/optimizationservice/Visits",
                method: "POST",
                data: entity,
                timeoutMS: 500,
                async: (entity.Category !== $home.optimization.ExitCategory)
            }, $.noop, $.noop);
        },

        start: function () {
            $home.optimization.internal.updateVisitCookie();
            var entity = $home.optimization.internal.createVisitEntity($home.optimization.EnterCategory);
            $home.optimization.visit(entity);
            window.onbeforeunload = function () {
                var entity = $home.optimization.internal.createVisitEntity($home.optimization.ExitCategory);
                $home.optimization.visit(entity);
            };
        },

        internal: {
            createVisitEntity: function (category) {
                var result = {
                    VisitorId: $.cookie("home_visitor_id"),
                    Category: category,
                    Url: document.URL,
                    Referer: document.referrer
                };

                if (navigator) {
                    result.Agent = navigator.userAgent;
                    // TODO: result.Geolocation = navigator.geolocation;
                    result.Language = navigator.language;
                    result.Platform = navigator.platform;
                }

                return result;
            },

            updateVisitCookie: function () {
                if ($.cookie('home_visitor_id') == null) {
                    $.cookie('home_visitor_id', $home.utility.guid.generate(), { expires: new Date(2050, 1, 1), path: '/' });
                }
            }
        },

        EnterCategory: "Enter",
        ExitCategory: "Exit",
        AjaxCategory: "Ajax",
        ActionCategory: "Action"
    };
})();

// *** init ***

// start visit optimization
$home.optimization.start();

$(function () {
    if (!console.error) {
        console.error = console.log;
    }

    if ($.fn.modal) {
        $.fn.modal.Constructor.DEFAULTS.backdrop = "static";
    }

    if ($.datepicker) {
        $.datepicker.setDefaults($.datepicker.regional["zh-CN"]);
    }

    $(document).ajaxError(function (event, xhr, settings, error) {
        console.error("%s %s\n%s", settings.type || settings.method, settings.url, error);
    });

    if (odatajs) {
        odatajs.oData.defaultError = function (error) {
            var request = error.request;
            var response = error.response;
            console.error("%s %s\n%s\n%s, %s\n%s", request.method, request.requestUri, error.message, response.statusCode, response.statusText, response.body);
        };
    }
});
